import redis
from random import choice

'''
维护一个代理池
使用python对redis数据库实现增删改查操作
'''

MAX_SCORE = 100
MIN_SCORE = 0
INITAL_SCORE = 10
REDIS_HOST = 'localhost'
REDIS_PORT = 6379
REDIS_PASSWORD = 'test'
#REDIS_KEY 有序集合的健名称，可以通过它来获取代理存储所使用的有序集合，相当于表名称
REDIS_KEY = 'proxies'

class RedisClient(object):
    def __init__(self,host = REDIS_HOST,port = REDIS_PORT,password = REDIS_PASSWORD):
        '''
        初始化，在初始化方法中链接redis数据库
        :param host: redis主机地址
        :param port:redis运行端口
        :param password:redis密码
        '''
        self.db = redis.StrictRedis(host=host, port=port, password=password,decode_responses= True)
        print('connect to redis database sucessful.')

    def add(self,proxy,score=INITAL_SCORE):
        '''
        添加代理，设置分数为最高
        :param proxy:代理
        :param score:分数
        :return:添加结果
        '''

        #返回有序集 key 中，成员 member 的 score 值;如果 member 元素不是有序集 key 的成员，或 key 不存在，返回 null
        if not self.db.zscore(REDIS_KEY,proxy):
            dict_score ={}
            dict_score[proxy] = score
            #注意dict_score中score和字符串的位置，
            # zadd 命令用于将一个或多个成员元素及其分数值加入到有序集当中，第一个参数为键名称，第二个参数为字典类型
            return self.db.zadd(REDIS_KEY,dict_score)

    def random(self):
        '''
        随机获取有效代理，首先尝试获取最高分数的有效代理，如果最高分数不存在，则按照排名获取，否则抛出异常
        :return:随机有效代理
        '''


        #返回有序集 key 中，所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。有序集成员按 score 值递增(从小到大)次序排列
        result = self.db.zrangebyscore(REDIS_KEY,MAX_SCORE,MAX_SCORE)
        if len(result):
            return choice(result)

        else:
            #返回有序集 key 中，指定区间内的成员。其中成员的位置按 score 值递减(从大到小)来排列。
            result = self.db.zrevrange(REDIS_KEY,0,100)
            if len(result):
                return choice(result)
            else:
                print('no proxy')

    def decrease(self,proxy):
        '''
        代理值减1分，分数小于最小值时，将代理直接删除

        :param proxy:代理
        :return:修改后的代理分数
        '''
        score = self.db.zscore(REDIS_KEY,proxy)
        if score and score > MIN_SCORE:
            print('代理 ：',proxy,'当前分数 ：', score,'减1')
            #为有序集 key 的成员 member 的 score 值加上增量 increment
            return self.db.zincrby(REDIS_KEY,-1,proxy)
        else:
            print('代理 ：', proxy, '当前分数 ：', score, '删除')
            #移除有序集 key 中的一个或多个成员，不存在的成员将被忽略
            return self.db.zrem(REDIS_KEY,proxy)

    def exists(self,proxy):
        '''
        判断代理是否存在
        :param proxy:代理
        :return:如果存在，返回True，否则返回False
        '''
        if self.db.zscore(REDIS_KEY,proxy):
            return True
        else:
            return False

    def max(self,proxy):
        '''
        将代理的分数设置为MAX_SCORE
        :param proxy:代理
        :return:设置结果
        '''
        print('代理 ：', proxy, '可用，分数这是为', MAX_SCORE)
        dict_max = {}
        dict_max[proxy] = MAX_SCORE
        #zadd 将一个或多个 member 元素及其 score 值加入到有序集 key 当中。
        #如果某个 member 已经是有序集的成员，那么更新这个 member 的 score 值，并通过重新插入这个 member 元素，来保证该 member 在正确的位置上
        #返回值：被成功添加的新成员的数量，不包括那些被更新的、已经存在的成员
        return self.db.zadd(REDIS_KEY,dict_max)

    def count(self):
        '''
        获取数量
        :return:数量
        '''
        return self.db.zcard(REDIS_KEY)

    def all(self):
        '''
        获取全部代理
        :return:全部代理
        '''
        return self.db.zrangebyscore(REDIS_KEY,MIN_SCORE,MAX_SCORE)

# if __name__=='__main__':
#     rc = RedisClient()
#     print(rc.random())